import os
import sys
import re
import math
from pathlib import Path
from PIL import Image
import pygame
from moviepy import ImageSequenceClip


# -------------------------- 配置参数 --------------------------
IMAGE_FOLDER = r"../add_text/pomeranian_visual_reports_final"
OUTPUT_VIDEO_PATH = r"../add_text/photo_book_animation_HORIZONTAL.mp4"  # 最终横版输出文件名
# ⚠️ 关键修正：设置回横版高清分辨率 (720p)
WINDOW_WIDTH, WINDOW_HEIGHT = 1280, 720
FLIP_DURATION = 0.4
STAY_DURATION = 1.2
FPS = 30
MAX_TOTAL_DURATION = 60.0
SUPPORTED_FORMATS = (".png", ".jpg", ".jpeg", ".bmp")
BACKGROUND_COLOR = (240, 240, 240)
PAGE_TIP_COLOR = (80, 80, 80)


# --------------------------------------------------------------


def natural_sort_key(s):
    """自然排序函数"""
    filename = os.path.splitext(os.path.basename(s))[0]
    parts = re.split(r'(\d+)', filename)
    key_parts = []
    for part in parts:
        if part.isdigit():
            key_parts.append(int(part))
        else:
            key_parts.append(part.lower())
    return key_parts


def load_images(folder_path):
    """加载图片，缩放至横版画布 (1280x720)"""
    folder = Path(folder_path).resolve()
    if not folder.exists() or not folder.is_dir():
        print(f"❌ 错误：图片文件夹不存在 → {folder}")
        sys.exit(1)

    image_paths = [file for file in folder.glob("*") if file.suffix.lower() in SUPPORTED_FORMATS]
    image_paths = sorted(image_paths, key=natural_sort_key)

    if not image_paths or len(image_paths) < 2:
        if not image_paths: print(f"❌ 错误：文件夹中未找到支持的图片")
        if len(image_paths) < 2: print(f"❌ 错误：至少需要2张图片")
        sys.exit(1)

    images = []
    for img_path in image_paths:
        try:
            with Image.open(img_path).convert("RGB") as pil_img:
                # --------------------- 🚀 核心修正：直接缩放至横版画布 ---------------------
                # 图片将根据 (1280, 720) 的尺寸进行缩放。如果原始图片不是 16:9，
                # 可能会有轻微拉伸或变形，但它会完全填充整个画布。
                pil_img = pil_img.resize((WINDOW_WIDTH, WINDOW_HEIGHT), Image.Resampling.LANCZOS)
                # ---------------------------------------------------------------------

                pygame_img = pygame.image.fromstring(pil_img.tobytes(), pil_img.size, "RGB")
                images.append(pygame_img)
            print(f"✅ 加载成功：{img_path.name}")
        except Exception as e:
            print(f"⚠️  跳过损坏图片：{img_path.name} → 错误：{str(e)[:30]}...")

    print(f"\n📊 图片加载完成 → 共{len(images)}张可用图片（按自然顺序排序）")
    return images


def draw_book_page(screen, current_img, next_img, progress, current_page_num, total_pages):
    """
    V8.0 绘制逻辑：适配横版，翻页仍然是横向翻动。
    """
    screen.fill(BACKGROUND_COLOR)
    total_width, total_height = WINDOW_WIDTH, WINDOW_HEIGHT

    # ------------------ 1. 绘制下一页 (作为背景) ------------------
    if next_img:
        screen.blit(next_img, (0, 0))

    # ------------------ 2. 绘制未翻折的当前页 (左侧矩形部分) ------------------
    unflipped_width = total_width - int(total_width * progress)

    if unflipped_width > 0:
        left_part_rect = pygame.Rect(0, 0, unflipped_width, total_height)
        screen.blit(current_img.subsurface(left_part_rect), (0, 0))

    # ------------------ 3. 绘制翻折部分 (使用 transform 模拟) ------------------
    flip_width = total_width - unflipped_width

    if flip_width > 0:
        flip_source_rect = pygame.Rect(unflipped_width, 0, flip_width, total_height)
        flip_surface_orig = current_img.subsurface(flip_source_rect).copy()

        angle = -180 * progress
        scale_factor = 1.0 - 0.3 * math.sin(progress * math.pi)

        transformed_flip = pygame.transform.rotozoom(flip_surface_orig, angle, scale_factor)

        y_lift = -int(total_height * 0.08 * math.sin(progress * math.pi))
        x_draw = unflipped_width

        transformed_rect = transformed_flip.get_rect(topleft=(x_draw, 0))
        transformed_rect.x -= transformed_flip.get_width() / 2
        transformed_rect.y += y_lift

        screen.blit(transformed_flip, transformed_rect.topleft)

        # ------------------ 4. 动态阴影 ------------------
        shadow_area_width = int(total_width * 0.15 * math.sin(progress * math.pi))
        if shadow_area_width > 0:
            shadow_surface = pygame.Surface((shadow_area_width, total_height), pygame.SRCALPHA)

            for x in range(shadow_area_width):
                alpha = int(120 * (1.0 - x / shadow_area_width) * math.sin(progress * math.pi))
                color = (0, 0, 0, alpha)
                pygame.draw.line(shadow_surface, color, (x, 0), (x, total_height), 1)

            shadow_x = unflipped_width - shadow_area_width
            screen.blit(shadow_surface, (shadow_x, 0))

    # 绘制页码提示 (调整到横版视频的角落)
    try:
        page_font = pygame.font.SysFont("Arial", 28, bold=True)
        page_text = f"第{current_page_num}页 / 共{total_pages}页"
        text_surface = page_font.render(page_text, True, PAGE_TIP_COLOR)
        screen.blit(text_surface, (total_width - text_surface.get_width() - 30, total_height - 40))
    except Exception:
        pass


def capture_frame(screen):
    """捕获帧并转为 NumPy 数组"""
    return pygame.surfarray.array3d(screen).copy()


def generate_book_video(images):
    """生成翻书视频的主循环，使用 MoviePy 输出 MP4"""
    pygame.init()
    screen = pygame.display.set_mode((WINDOW_WIDTH, WINDOW_HEIGHT), pygame.SRCALPHA)
    pygame.display.set_caption("生成高质量 MP4 视频...")

    total_pages = len(images)
    all_frames = []
    total_time = 0.0
    num_flip_frames = int(FLIP_DURATION * FPS)
    num_stay_frames = int(STAY_DURATION * FPS)

    print(f"\n🎬 开始生成视频 → 总页数：{total_pages} | 输出路径：{Path(OUTPUT_VIDEO_PATH).resolve()}")

    try:
        for i in range(total_pages):
            current_page_idx = i
            next_page_idx = i + 1 if i < total_pages - 1 else None

            current_img = images[current_page_idx]
            next_img = images[next_page_idx] if next_page_idx is not None else None

            # ------------------ 1. 停留帧 ------------------
            for _ in range(num_stay_frames):
                draw_book_page(screen, current_img, next_img, 0.0, current_page_idx + 1, total_pages)
                all_frames.append(capture_frame(screen))

            total_time += STAY_DURATION

            # ------------------ 2. 翻页帧 (如果不是最后一页) ------------------
            if next_page_idx is not None:
                for j in range(num_flip_frames):
                    progress = (j + 1) / num_flip_frames

                    draw_book_page(screen, current_img, next_img, progress, current_page_idx + 1, total_pages)
                    all_frames.append(capture_frame(screen))

                total_time += FLIP_DURATION

            if total_time > MAX_TOTAL_DURATION:
                print(f"⚠️  视频时长超出限制（{MAX_TOTAL_DURATION:.1f}秒），自动停止")
                break

            progress_percent = (i / total_pages) * 100
            print(f"🖼️  页面进度: {progress_percent:.0f}% | 已捕获 {len(all_frames)} 帧")

    except Exception as e:
        print(f"\n❌ 生成帧过程出错：{e}")
        pygame.quit()
        sys.exit(1)

    # -------------------------- 合成并保存 MP4 --------------------------
    if all_frames:
        print("\n💾 正在合成视频，请稍候...")
        try:
            clip = ImageSequenceClip(all_frames, fps=FPS)

            # ⚠️ 关键修正：移除 ['-metadata:s:v', 'rotate=0']，让视频保持默认横版方向
            clip.write_videofile(
                OUTPUT_VIDEO_PATH,
                codec='libx264',
                audio=False,
                fps=FPS,
                logger=None
            )

            if os.path.exists(OUTPUT_VIDEO_PATH) and os.path.getsize(OUTPUT_VIDEO_PATH) > 1024:
                file_size = os.path.getsize(OUTPUT_VIDEO_PATH) // 1024
                print(f"\n🎉 视频生成成功！(V8.0 最终横版输出版)")
                print(f"📁 路径：{Path(OUTPUT_VIDEO_PATH).resolve()}")
                print(f"📊 大小：{file_size} KB | 总时长：{total_time:.1f} 秒 | 帧率：{FPS}")
            else:
                print(f"\n❌ 视频生成失败：文件为空或过小")

        except Exception as e:
            print(f"\n❌ 保存视频失败：{e}")
    else:
        print(f"\n❌ 无帧可合成：未捕获到任何有效帧")

    pygame.quit()
    print(f"\n👋 程序正常结束")


if __name__ == "__main__":
    output_dir = Path(OUTPUT_VIDEO_PATH).parent
    if not output_dir.exists():
        output_dir.mkdir(parents=True, exist_ok=True)
        print(f"✅ 已创建输出文件夹：{output_dir}")

    if not pygame.get_init():
        pygame.init()

    book_images = load_images(IMAGE_FOLDER)
    generate_book_video(book_images)